<script lang="ts" setup>
import type {
  DropdownAppearance,
  DropdownSize,
  DropdownType,
} from '@fluentui/web-components';

const props = withDefaults(
  defineProps<{
    appearance?: keyof typeof DropdownAppearance;
    autoFocus?: boolean;
    disabled?: boolean;
    open?: boolean;
    placeholder?: string;
    required?: boolean;
    size?: DropdownSize;
    type?: DropdownType;
  }>(),
  {
    appearance: 'outline',
    size: undefined,
    type: 'dropdown',
    disabled: false,
    required: false,
    placeholder: undefined,
    open: undefined,
    autoFocus: false,
  },
);

// Define emitted events
const emit = defineEmits<{
  change: [event: Event];
  'update:open': [isOpen: boolean];
}>();

// Define the model value for v-model support
const selectedValue = defineModel<string | string[]>();

// Reference to the dropdown element
// Using HTMLElement & { value: string | string[] } to add value property to the type
const dropdownRef = ref<(HTMLElement & { value: string | string[] }) | null>();

// When component mounts, set focus if autoFocus is true
watch(
  () => props.autoFocus,
  (value) => {
    if (value && dropdownRef.value) {
      dropdownRef.value.focus();
    }
  },
  { immediate: true },
);

// Track open state and handle updates
const handleDropdownChange = (event: Event) => {
  const target = event.target as HTMLElement & { value: string | string[] };
  // Update the selectedValue when dropdown changes
  if (target && target.value !== undefined) {
    selectedValue.value = target.value;
  }
  emit('change', event);
};

// Watch for changes to the dropdown's open state
watch(
  () => props.open,
  (newValue) => {
    if (
      dropdownRef.value && // Due to limitations in the FluentUI web components, we need to manually
      // trigger open/close behavior in some cases
      newValue !== undefined
    ) {
      if (newValue) {
        dropdownRef.value.setAttribute('open', '');
      } else {
        dropdownRef.value.removeAttribute('open');
      }
    }
  },
  { immediate: true },
);

// Handler for when the dropdown is opened or closed
const handleOpenStateChange = (event: Event) => {
  const target = event.target as HTMLElement;
  const isOpen = target.hasAttribute('open');
  emit('update:open', isOpen);
};

// Watch for changes to the selectedValue from the parent component
watch(
  () => selectedValue?.value,
  (newValue) => {
    if (dropdownRef.value && newValue !== undefined) {
      // Schedule this update after the component is fully mounted and DOM is updated
      nextTick(() => {
        // Update the dropdown's value attribute
        if (dropdownRef.value) {
          dropdownRef.value.value = newValue;
        }
      });
    }
  },
  { immediate: true },
);
onMounted(() => {
  nextTick(async () => {
    for (let i = 0; i < 10; i++) {
      await new Promise((resolve) => setTimeout(resolve, 100));
      if (dropdownRef.value && selectedValue.value) {
        dropdownRef.value.value = selectedValue.value || '';
      }
    }
  });
});
</script>

<template>
  <fluent-dropdown
    ref="dropdownRef"
    :appearance="appearance"
    :size="size"
    :type="type"
    :disabled="disabled"
    :required="required"
    :placeholder="placeholder"
    @change="handleDropdownChange"
    @click="handleOpenStateChange"
  >
    <slot></slot>
  </fluent-dropdown>
</template>

<style scoped></style>
